﻿using CGT.API.API;
using CGT.API.Common;
using CGT.API.Models;
using Newtonsoft.Json.Linq;
using OF.Component.BLL;
using OF.Component.Enum;
using OF.Component.Model;
using OF.Utility;
using OF.Utility.Logging;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;

namespace CGT.API.Controllers
{
    /// <summary>
    /// AI用户认证
    /// </summary>
    public class AuthenticationAIController : BaseApiController
    {
        #region 电话认证

        /// <summary>
        /// 用户根据电话号码注册
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public ResultData<long> AddUserMobile(UserMobileVerCodeModel model)
        {
            SMSClient smsClient = new SMSClient();
            ResultDataOfBoolean valid = smsClient.CheckVerificationCodeAsync(model.UserMobile, model.VerCode, 100).Result;
            if (!valid.Data.Value)
            {
                return ResultData<long>.Error("验证码错误,请重新输入");
            }

            var oExistedUser = UserOperate.GetUserByMobile(model.UserMobile);
            if (oExistedUser == null)
            {
                oExistedUser = new UserInfo();
                oExistedUser.CreatedDate = DateTime.Now;
                oExistedUser.UpdatedDate = DateTime.Now;
                oExistedUser.IsActive = 1;
                oExistedUser.UserType = 1;
                oExistedUser.UserLevel = 0;
                oExistedUser.UserMobile = model.UserMobile;
                oExistedUser.UserID = UserOperate.Insert(oExistedUser);
            }

            //更新第三方来源信息
            if (!string.IsNullOrEmpty(model.ThirdUserID))
            {
                var userSourceInfo = UserSourceOperate.GetByToken(model.ThirdUserID, model.ThirdUserSource);
                if (userSourceInfo != null)
                {
                    userSourceInfo.UserID = oExistedUser.UserID;
                    UserSourceOperate.Update(userSourceInfo);
                }
            }
            //UserCenterClient userClient = new UserCenterClient();
            //ResultDataOfResponseUserAdd userAdd = userClient.User_AddOrGetAsync(new RequestUserAdd()
            //{
            //    UserType = 1,
            //    UserLevel = 0,
            //    SourceToken = model.ThirdUserID,
            //    SourceType = model.ThirdUserSource,
            //    UserMobile = model.UserMobile
            //}).Result;

            return ResultData<long>.Success(oExistedUser.UserID);
        }

        #endregion

        #region 身份证认证

        /// <summary>
        /// 身份证识别
        /// </summary>
        /// <returns>身份证识别信息</returns>
        [HttpPost]
        [AllowAnonymous]
        public Task<ResultData<IdcardOCRModel>> IdCardOCR()
        {
            // 确定指定的内容是否是 MIME 多部分内容
            if (!Request.Content.IsMimeMultipartContent())
            {
                throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
            }

            //用户id 用于创建单用户单文件夹
            string userID = HttpContext.Current.Request["UserID"];
            //身份证正面反面  反面不需要进行解析
            string cardType = HttpContext.Current.Request["CardType"];

            //指定要将文件存入的服务器物理位置  
            string certificatePath = ConfigHelper.GetValue("TencentAI.FilePath") + userID;
            if (!Directory.Exists(certificatePath))
            {
                Directory.CreateDirectory(certificatePath);
            }
            var provider = new MultipartFormDataStreamProvider(certificatePath);

            var task = Request.Content.ReadAsMultipartAsync(provider).
                ContinueWith<ResultData<IdcardOCRModel>>(t =>
                {
                    if (t.IsFaulted || t.IsCanceled)
                    {
                        Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
                    }
                    //文件保存
                    List<string> files = InnerUploadFile(provider.FileData);
                    if (cardType == "0")  //身份证正面
                    {
                        //文件识别
                        //var ocrApi = new TencentAI();
                        var ocrApi = new BaiduAI();
                        string strResult = ocrApi.ocr_idcardocr(files.FirstOrDefault(), cardType);
                        ResultData<IdcardOCRModel> result = ocrApi.ParseIdCardResult(strResult, cardType);
                        if (result.status != 0)
                        {
                            return result;
                        }
                        result.data.ImgageName = GetFileName(files.FirstOrDefault());

                        //同步到用户中心
                        //UserCenterClient usrCenter = new UserCenterClient();
                        var oExist = IDCardOperate.GetByUserIDAndNum(EConvert.ToLong(userID), result.data.Id);
                        if (oExist != null)
                        {
                            oExist.Name = result.data.Name;
                            oExist.Sex = result.data.Sex == "男" ? 1 : 2;
                            oExist.Folk = result.data.Nation;
                            oExist.Birth = EConvert.ToDateTime(result.data.Birth);
                            oExist.Address = result.data.Address;
                            oExist.IDNum = result.data.Id;
                            oExist.PicPath = result.data.ImgageName;
                            oExist.Dep = result.data.Authority;
                            oExist.UpdatedDate = DateTime.Now;
                            oExist.IsActive = 1;
                            IDCardOperate.Update(oExist);
                        }
                        else
                        {
                            oExist = new IDCardInfo();
                            oExist.Name = result.data.Name;
                            oExist.Sex = result.data.Sex == "男" ? 1 : 2;
                            oExist.Folk = result.data.Nation;
                            oExist.Birth = EConvert.ToDateTime(result.data.Birth);
                            oExist.Address = result.data.Address;
                            oExist.IDNum = result.data.Id;
                            oExist.PicPath = result.data.ImgageName;
                            oExist.Dep = result.data.Authority;
                            oExist.UpdatedDate = DateTime.Now;
                            oExist.CreatedDate = DateTime.Now;
                            oExist.IsActive = 1;
                            IDCardOperate.Insert(oExist);
                        }
                        //var idCardTask = usrCenter.IDCard_AddOrUpdateAsync(new ReqIDCardAdd()
                        //{
                        //    UserID = EConvert.ToLong(userID),
                        //    Name = result.data.Name,
                        //    Sex = result.data.Sex == "男" ? 1 : 2,
                        //    Folk = result.data.Nation,
                        //    Birth = EConvert.ToDateTime(result.data.Birth),
                        //    Address = result.data.Address,
                        //    IDNum = result.data.Id,
                        //    PicPath = result.data.ImgageName,
                        //    Dep = result.data.Authority
                        //}).Result;

                        return result;
                    }
                    else  //身份证背面
                    {
                        ResultData<IdcardOCRModel> result = new ResultData<IdcardOCRModel>();
                        result.data = new IdcardOCRModel()
                        {
                            ImgageName = GetFileName(files.FirstOrDefault())
                        };
                        return result;
                    }
                });
            return task;
        }
        #endregion

        /// <summary>
        /// 用户授权
        /// </summary>
        /// <returns></returns>
        public ResultData<long> AddUserAuth(UserAuthModel model)
        {
            var nInsertID = UserAuthOperate.Insert(new UserAuthInfo()
            {
                CertificateCreateDate = DateTime.Now,
                CertificatePath = model.CertificatePath,
                CertificateBackPath = model.CertificateBackPath,
                CertificateType = 1,
                UserID = model.UserID,
                IsActive = 1,
                AuthLevel = (int)AuthLevelEnum.IDCard,
                VideoCreatedDate = DateTime.Now
            });
            //UserOperate.UpdateUserLevel(reqInfo.UserID, 1);
            //UserCenterClient usrClient = new UserCenterClient();

            //ResultDataOfResponseUserAuthResult userAdd = usrClient.UserAuth_AddAsync(new RequestUserAuthAdd()
            //{
            //    CertificateCreateDate = DateTime.Now,
            //    CertificatePath = model.CertificatePath,
            //    CertificateBackPath = model.CertificateBackPath,
            //    CertificateType = 1,
            //    UserID = model.UserID
            //}).Result;

            return ResultData<long>.Success(nInsertID);
        }

        #region 语音认证

        /// <summary>
        /// 录音识别
        /// </summary>
        /// <returns>返回用户认证级别</returns>
        [HttpPost]
        public Task<ResultData<int>> ASR()
        {
            // 确定指定的内容是否是 MIME 多部分内容
            if (!Request.Content.IsMimeMultipartContent())
            {
                throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
            }

            string userID = HttpContext.Current.Request["UserID"];
            string verCode = HttpContext.Current.Request["VerCode"];  //验证码

            //指定要将文件存入的服务器物理位置  
            string certificatePath = ConfigHelper.GetValue("TencentAI.FilePath") + userID;
            if (!Directory.Exists(certificatePath))
            {
                Directory.CreateDirectory(certificatePath);
            }
            var provider = new MultipartFormDataStreamProvider(certificatePath);

            var task = Request.Content.ReadAsMultipartAsync(provider).
                ContinueWith<ResultData<int>>(t =>
                {
                    if (t.IsFaulted || t.IsCanceled)
                    {
                        Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
                    }

                    //文件保存
                    List<string> files = InnerUploadFile(provider.FileData);
                    //文件转换
                    List<string> wavFiles = Mp3ToWav(files);
                    //文件识别
                    ResultData<ASRModel> result = null;
                    try
                    {
                        var ocrApi = new BaiduAI();
                        // var ocrApi = new TencentAI();
                        var strResult = ocrApi.aai_asr(wavFiles[0]);
                        //Log4netLog.Debug(strResult);
                        result = ocrApi.ParseASRResult(strResult);
                    }
                    catch (Exception ex)
                    {
                        Log4netLog.Debug(ex.Message);
                        result = new ResultData<ASRModel>()
                        {
                            status = 3,
                            message = ex.Message
                        };
                    }

                    ResultData<int> rt = new ResultData<int>();

                    if (result.status == 0)
                    {
                        // 3:声音内容不清晰,4:声音内容不正确
                        if (ChineseToDigit(result.data.Text) != verCode)
                        {
                            if (result.message.Contains("清晰"))
                            {
                                rt.status = 3;
                            }
                            else
                            {
                                rt.status = 4;
                            }
                        }
                        else
                        {
                            UserAuthInfo oExistedUserAuth = UserAuthOperate.GetByUser(EConvert.ToLong(userID));
                            if (oExistedUserAuth != null)
                            {
                                oExistedUserAuth.VideoCreatedDate = DateTime.Now;
                                if (oExistedUserAuth.AuthLevel == (int)AuthLevelEnum.Vedio)
                                {
                                    oExistedUserAuth.AuthLevel = (int)AuthLevelEnum.Complete;
                                }
                                else
                                {
                                    oExistedUserAuth.AuthLevel = (int)AuthLevelEnum.ASR;
                                }
                                UserAuthOperate.Update(oExistedUserAuth);
                                UserOperate.UpdateUserLevel(EConvert.ToLong(userID), oExistedUserAuth.AuthLevel);
                            }
                            ////同步到用户授权
                            //UserCenterClient usrClient = new UserCenterClient();
                            //ResultDataOfResponseUserAuthResult usrAuth = usrClient.UserAuth_AddAsrAsync(new RequestUserAuthASR() { UserAuthID = 0, UserID = EConvert.ToLong(userID) }).Result;
                            //if (usrAuth.Status == 0)
                            //{
                            //    rt.data = usrAuth.Data.AuthLevel.Value;
                            //}
                            rt.data = oExistedUserAuth.AuthLevel;
                        }
                    }
                    else
                    {
                        rt.status = 3;
                    }

                    rt.message = result.message;
                    return rt;
                });
            return task;
        }

        /// <summary>
        /// mp3转wav
        /// </summary>
        /// <returns></returns>
        protected List<string> Mp3ToWav(List<string> files)
        {
            List<string> cvrFiles = new List<string>(files.Count);
            try
            {
                var psi = new ProcessStartInfo();
                psi.FileName = ConfigHelper.GetValue("TencentAI.ffmpegPath");
                psi.RedirectStandardOutput = true;
                psi.RedirectStandardError = true;
                psi.UseShellExecute = false;
                foreach (string file in files)
                {
                    int idx = file.LastIndexOf('.');
                    string cvrFile = file.Substring(0, idx) + ".wav";
                    psi.Arguments = $"-i \"{file}\" \"{cvrFile}\"";
                    var process = Process.Start(psi);
                    process.WaitForExit((int)TimeSpan.FromSeconds(60).TotalMilliseconds);
                    cvrFiles.Add(cvrFile);
                }
            }
            catch (Exception ex)
            {
                Log4netLog.Debug(ex.Message);
                Log4netLog.Debug(ex.StackTrace);
                Log4netLog.Debug(ex.Source);
            }
            return cvrFiles;
        }

        #endregion

        #region 人脸识别认证

        /// <summary>
        /// 视频上传
        /// </summary>
        /// <returns>返回用户认证级别</returns>
        [HttpPost]
        public Task<ResultData<int>> FaceCompare()
        {
            // 确定指定的内容是否是 MIME 多部分内容
            if (!Request.Content.IsMimeMultipartContent())
            {
                throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
            }

            string userID = HttpContext.Current.Request["UserID"];
            string imgName = HttpContext.Current.Request["IdCardImage"];

            //用如果只是身份证认证，下次进入页面需要根据用查询身份证的名称
            if (string.IsNullOrEmpty(imgName))
            {
                var oInfo = UserAuthOperate.GetByUser(EConvert.ToLong(userID));
                if (oInfo != null)
                {
                    imgName = oInfo.CertificatePath;
                }
                //UserCenterClient usrClient = new UserCenterClient();
                //ResultDataOfResponseUserAuthGet usrAuth = usrClient.UserAuth_GetByUserAsync(EConvert.ToLong(userID)).Result;
                //if (usrAuth.Status == 0)
                //{
                //    imgName = usrAuth.Data.CertificatePath;
                //}
            }

            //指定要将文件存入的服务器物理位置  
            string certificatePath = ConfigHelper.GetValue("TencentAI.FilePath") + userID;
            Log4netLog.Debug("certificatePath:" + certificatePath);
            if (!Directory.Exists(certificatePath))
            {
                Directory.CreateDirectory(certificatePath);
            }
            var provider = new MultipartFormDataStreamProvider(certificatePath);

            var task = Request.Content.ReadAsMultipartAsync(provider).
                ContinueWith<ResultData<int>>(t =>
                {
                    if (t.IsFaulted || t.IsCanceled)
                    {
                        Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
                    }
                    //文件保存
                    List<string> files = InnerUploadFile(provider.FileData);
                    //文件截图
                    VideoSnapshots(files);
                    //身份证截取头像
                    string compareFile = certificatePath + "\\Head_" + imgName;
                    ImageRect(certificatePath + "\\" + imgName, compareFile);

                    ResultData<FaceCompareModel> result = new ResultData<FaceCompareModel>();
                    ResultData<int> rt = new ResultData<int>();

                    foreach (string file in files)
                    {
                        int idx = file.LastIndexOf("\\");
                        int dotIdx = file.LastIndexOf(".");
                        string[] vedioFiles = Directory.GetFiles(file.Substring(0, idx));
                        foreach (string vfile in vedioFiles)
                        {
                            Log4netLog.Debug("FaceCompare-vfile:" + vfile);
                            string vFileName = vfile.Substring(idx + 1);
                            string fileName = file.Substring(idx + 1, dotIdx - idx - 1);
                            if (vFileName.StartsWith(fileName))
                            {
                                try
                                {
                                    var ocrApi = new BaiduAI();
                                    string strResult = ocrApi.face_facecompare(vfile, compareFile);
                                    Log4netLog.Debug(strResult);
                                    result = ocrApi.ParseFaceCompareResult(strResult);
                                }
                                catch (Exception ex)
                                {
                                    Log4netLog.Debug(ex.Message);
                                    result = new ResultData<FaceCompareModel>()
                                    {
                                        status = 3,
                                        message = ex.Message
                                    };
                                }

                                if (result.status == 0)
                                {
                                    Log4netLog.Debug(Convert.ToString(result.data.Similarity));
                                    if (result.data.Similarity > 50)
                                    {
                                        UserAuthInfo oExistedUserAuth = UserAuthOperate.GetByUser(EConvert.ToLong(userID));

                                        if (oExistedUserAuth != null)
                                        {
                                            oExistedUserAuth.VideoCreatedDate = DateTime.Now;
                                            if (oExistedUserAuth.AuthLevel == (int)AuthLevelEnum.ASR)
                                            {
                                                oExistedUserAuth.AuthLevel = (int)AuthLevelEnum.Complete;
                                            }
                                            else
                                            {
                                                oExistedUserAuth.AuthLevel = (int)AuthLevelEnum.Vedio;
                                            }
                                            UserAuthOperate.Update(oExistedUserAuth);
                                            UserOperate.UpdateUserLevel(oExistedUserAuth.UserID, oExistedUserAuth.AuthLevel);
                                        }

                                        rt.data = oExistedUserAuth.AuthLevel;
                                        ////同步到用户授权
                                        //UserCenterClient usrClient = new UserCenterClient();
                                        //ResultDataOfResponseUserAuthResult usrAuth = usrClient.UserAuth_AddVideoAsync(new RequestUserAuthVideoAdd()
                                        //{
                                        //    UserAuthID = 0,
                                        //    UserID = EConvert.ToLong(userID),
                                        //    VideoScreenPath = vFileName,
                                        //    VideoPath = GetFileName(file)
                                        //}).Result;
                                        //if (usrAuth.Status == 0)
                                        //{
                                        //    rt.data = usrAuth.Data.AuthLevel.Value;
                                        //}
                                        break;
                                    }
                                    else
                                    {
                                        rt.status = 3;
                                    }
                                }
                                else
                                {
                                    rt.status = 2;
                                    break;
                                }
                                rt.message = result.message;
                            }
                        }
                    }
                    return rt;
                });
            return task;
        }

        /// <summary>
        /// 视频截图
        /// </summary>
        /// <returns></returns>
        public List<string> VideoSnapshots(List<string> files)
        {
            try
            {
                var psi = new ProcessStartInfo();
                psi.FileName = ConfigHelper.GetValue("TencentAI.ffmpegPath");
                psi.RedirectStandardOutput = true;
                psi.RedirectStandardError = true;
                psi.UseShellExecute = false;
                foreach (string file in files)
                {
                    int idx = file.LastIndexOf('.');
                    string pngFile = file.Substring(0, idx) + "-%03d.png";
                    psi.Arguments = $"-i {file} -r 0.5 -q:v 2 -f image2 {pngFile}";  //2秒截图一次
                    var process = Process.Start(psi);
                    process.WaitForExit((int)TimeSpan.FromSeconds(60).TotalMilliseconds);
                }
            }
            catch (Exception ex)
            {
                Log4netLog.Debug(ex.Message);
                Log4netLog.Debug(ex.StackTrace);
                Log4netLog.Debug(ex.Source);
            }
            return files;
        }

        /// <summary>
        /// 图像剪切
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public string ImageRect(string fromImagePath, string toImagePath)
        {
            Log4netLog.Debug("fromImagePath:" + fromImagePath);
            Log4netLog.Debug("toImagePath:" + toImagePath);

            //原图片文件
            using (Image fromImage = Image.FromFile(fromImagePath))
            {
                Rectangle rect;
                if (fromImage.Height > fromImage.Width)
                {
                    int offsetX = EConvert.ToInt(fromImage.Width * 0.3);
                    int offsetY = EConvert.ToInt(fromImage.Height * 0.65);
                    int width = fromImage.Width - offsetX;
                    int height = fromImage.Height - offsetY;
                    rect = new Rectangle(offsetX, offsetY, width, height);
                }
                else
                {
                    int offsetX = EConvert.ToInt(fromImage.Width * 0.65);
                    int offsetY = 0;
                    int width = fromImage.Width - offsetX;
                    int height = EConvert.ToInt(fromImage.Height * 0.7);
                    rect = new Rectangle(offsetX, offsetY, width, height);
                }

                //创建新图位图
                Bitmap bitmap = new Bitmap(rect.Width, rect.Height);
                //创建作图区域
                Graphics graphic = Graphics.FromImage(bitmap);
                //截取原图相应区域写入作图区
                graphic.DrawImage(fromImage, 0, 0, rect, GraphicsUnit.Pixel);
                //从作图区生成新图
                Image saveImage = Image.FromHbitmap(bitmap.GetHbitmap());
                //保存图片
                saveImage.Save(toImagePath, ImageFormat.Png);
                //释放资源   
                saveImage.Dispose();
                graphic.Dispose();
                bitmap.Dispose();
            }

            return toImagePath;
        }

        #endregion

        #region 公共

        /// <summary>
        /// 图片保存并返回相应路径
        /// </summary>
        /// <param name="files">文件集合</param>
        /// <returns></returns>
        protected List<string> InnerUploadFile(Collection<MultipartFileData> files)
        {
            List<string> filePaths = new List<string>(files.Count);
            try
            {
                //获取上传文件
                foreach (MultipartFileData file in files)
                {
                    //api默认保存的文件没有后缀名,需要重命名
                    FileInfo f = new FileInfo(file.LocalFileName);
                    int idx = file.Headers.ContentDisposition.FileName.LastIndexOf('.');
                    string pfx = file.Headers.ContentDisposition.FileName.Substring(idx).Replace("\"", string.Empty);
                    //api的文件名,自动添加了双引号(")，此处去掉，否则会提示非法路径。  真坑
                    string newFileName = file.LocalFileName.Replace("-", string.Empty);
                    string newFileNameWithPfx = newFileName + pfx;
                    f.MoveTo(newFileNameWithPfx);
                    filePaths.Add(newFileNameWithPfx);
                }
            }
            catch (Exception ex)
            {
                Log4netLog.Debug(ex.Message);
                Log4netLog.Debug(ex.StackTrace);
                Log4netLog.Debug(ex.Source);
            }
            return filePaths;
        }

        /// <summary>
        /// 获取文件名称
        /// </summary>
        /// <param name="fullFileName"></param>
        /// <returns></returns>
        protected string GetFileName(string fullFileName)
        {
            int idx = fullFileName.LastIndexOf("\\");
            return fullFileName.Substring(idx + 1);
        }

        /// <summary>
        /// 将汉字转换成数字
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        protected string ChineseToDigit(string str)
        {
            string result = "";
            if (string.IsNullOrEmpty(str))
            {
                return result;
            }

            string numString = "零一二三四五六七八九十";
            for (int i = 0; i < str.Length; i++)
            {
                int idx = numString.IndexOf(str[i]);
                if (idx > -1)
                {
                    result += idx;
                }
            }

            return result;
        }

        #endregion
    }
}
